package com.yf.tz.service.impl;

import com.gc.server.dao.UserDao;
import com.gc.server.entity.UserEntity;
import com.yf.response.RRException;
import com.yf.service.WxPayService;
import com.yf.service.impl.BaseServiceImpl;
import com.yf.tz.common.Const;
import com.yf.tz.dao.AccountDao;
import com.yf.tz.dao.AccountRecordDao;
import com.yf.tz.entity.*;
import com.yf.tz.enums.*;
import com.yf.tz.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 账户信息Service实现类
 *
 * @author hxf
 * @email 505860922@qq.com
 * @date Wed Jul 01 16:32:18 CST 2020
 */
@Service
public class AccountServiceImpl extends BaseServiceImpl<AccountEntity> implements AccountService {

    private AccountDao accountDao;


    @Autowired
    public void setDao(AccountDao accountDao) {
        this.accountDao = accountDao;
        super.setBaseDao(accountDao);
    }


    /**
     * 内部方法
     **/

    //转账
    void transfer(Long fromUserId, Long toUserId, BigDecimal amount, Integer type, String remark) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        if (!fromUserId.equals(Const.ADMIN_ID)) {
            decrease(fromUserId, amount, remark, "", type, AccountRecordBusEnum.TRANSFER.getIndex());
        }
        if (!toUserId.equals(Const.ADMIN_ID)) {
            increase(toUserId, amount, remark, "", type, AccountRecordBusEnum.TRANSFER.getIndex());
        }
    }


    //增加
    void increase(Long userId, BigDecimal amount, String remark, String orderNo, Integer type, Integer bus) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        findByUserIdAndType(userId, type);
        accountDao.increase(userId, type, amount);
        AccountEntity accountEntity = findByUserIdAndType(userId, type);
        //生成记录
        AccountRecordEntity recordEntity = new AccountRecordEntity(Const.ADMIN_ID, userId, type, AccountRecordStatusEnum.DONE.getIndex(), bus, amount, BigDecimal.ZERO, accountEntity.getAmount(), new Date(), remark, orderNo);
        accountRecordDao.save(recordEntity);
    }

    //减少
    void decrease(Long userId, BigDecimal amount, String remark, String orderNo, Integer type, Integer bus) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        AccountEntity accountEntity = findByUserIdAndType(userId, type);
        if (accountEntity.getAmount().compareTo(amount) < 0) {
            throw new RRException(AccountTypeEnum.indexOf(type) + "余额不足");
        }
        accountDao.decrease(userId, type, amount);
        accountEntity = findByUserIdAndType(userId, type);
        //生成记录
        AccountRecordEntity recordEntity = new AccountRecordEntity(userId, Const.ADMIN_ID, type, AccountRecordStatusEnum.DONE.getIndex(), bus, amount, accountEntity.getAmount(), BigDecimal.ZERO, new Date(), remark, orderNo);
        accountRecordDao.save(recordEntity);
    }

    //追回
    private void recoverToAdmin(Long userId, BigDecimal amount, String remark, String orderNo, Integer type) {
        decrease(userId, amount, remark, orderNo, type, AccountRecordBusEnum.RECOVER.getIndex());
    }

    //退给用户
    private void backToUser(Long userId, BigDecimal amount, String remark, String orderNo, Integer type) {
        increase(userId, amount, remark, orderNo, type, AccountRecordBusEnum.BACK.getIndex());
    }


    /**
     * 外部方法实现
     **/


    @Override
    public void adminTransfer(String fromUserName, String fromUserCode, String toUserName, String toUserCode, BigDecimal amount, Integer type, String remark) {
        //验证
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new RRException("金额填写有误!");
        }
        UserEntity fromUser = userDao.findByCode(fromUserCode);
        if (fromUser == null || !fromUser.getName().equals(fromUserName)) {
            throw new RRException("转账人信息有误!");
        }
        //批量转
        if(toUserCode.contains("_")){
            for (String userCode:toUserCode.split("_")){
                UserEntity tem = userDao.findByCode(userCode);
                if(tem!=null){
                    transfer(fromUser.getId(), tem.getId(), amount, type, remark);
                }
            }
        }else {
            UserEntity toUser = userDao.findByCode(toUserCode);
            if (toUser == null || !toUser.getName().equals(toUserName)) {
                throw new RRException("接收人信息有误!");
            }
            transfer(fromUser.getId(), toUser.getId(), amount, type, remark);
        }


    }

    @Autowired
    private UserDao userDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void usePoint(Long userId, BigDecimal amount, String remark, String orderNo) {
        decrease(userId, amount, remark, orderNo, AccountTypeEnum.POINT.getIndex(), AccountRecordBusEnum.PAY.getIndex());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void useCash(Long userId, BigDecimal amount, String remark, String orderNo) {
        decrease(userId, amount, remark, orderNo, AccountTypeEnum.CEC.getIndex(), AccountRecordBusEnum.PAY.getIndex());
    }

    @Override
    public void rewardPoint(Long userId, BigDecimal amount, String remark, String orderNo) {
        increase(userId, amount, remark, orderNo, AccountTypeEnum.POINT.getIndex(), AccountRecordBusEnum.REWARD.getIndex());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountEntity findByUserIdAndType(Long userId, Integer type) {
        AccountEntity accountEntity = accountDao.findByUserIdAndType(userId, type);
        if (accountEntity == null) {
            accountEntity = new AccountEntity(userId, BigDecimal.ZERO, type);
            accountDao.save(accountEntity);
        }
        return accountEntity;
    }


    @Override
    public void cancelOrder(MallOrderEntity orderEntity) {
        //找出与此订单所有相关的订单
        List<AccountRecordEntity> recordEntities = accountRecordDao.findByOrderNo(orderEntity.getOrderNo());
        recordEntities.forEach(item -> {
            //支付出去的公司还回来  奖励出去的退给公司
            if (item.getBus().equals(AccountRecordBusEnum.PAY.getIndex())) {
                backToUser(item.getFromUserId(), item.getAmount(), "取消订单退回", orderEntity.getOrderNo(), item.getType());
            }
            //奖励给用户的要退给公司
            if (item.getBus().equals(AccountRecordBusEnum.REWARD.getIndex())) {
                recoverToAdmin(item.getToUserId(), item.getAmount(), "取消订单追回", orderEntity.getOrderNo(), item.getType());
            }
        });
        //如果支付了且不是存储金支付的 以存储金的形式退给用户
        if (orderEntity.getPaid().equals(MallOrderPaidEnum.YES.getIndex()) && !orderEntity.getPayWay().equals(MallOrderPayWayEnum.CEC.getIndex())) {
            backToUser(orderEntity.getUserId(), orderEntity.getPay(), "取消订单退回", orderEntity.getOrderNo(), AccountTypeEnum.CEC.getIndex());
        }
    }



    //创建订单号
    private String createNO(Long userId) {
        return System.currentTimeMillis() + "" + Math.round(Math.random() * 100) + "" + userId;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String recharge(Long userId, BigDecimal amount) {
        String orderNo = createNO(userId);
        AccountRecordEntity recordEntity = new AccountRecordEntity(Const.ADMIN_ID, userId, AccountTypeEnum.CEC.getIndex(), AccountRecordStatusEnum.WAIT.getIndex(), AccountRecordBusEnum.CHARGE.getIndex(), amount, null, null, new Date(), "充值", orderNo);
        accountRecordDao.save(recordEntity);
        UserEntity userEntity = userDao.get(userId);
        String noticeUrl = ServletUriComponentsBuilder.fromCurrentContextPath().path(Const.MALL_ORDER_PAY_NOTICE_URL).build().toUriString();
        //调用支付
        String res = wxPayService.createAppConfig(recordEntity.getOrderNo(), recordEntity.getAmount().doubleValue(), recordEntity.getInfo(), userEntity.getOpenId(), noticeUrl);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rechargePay(String orderNo, BigDecimal totalPay) {
        AccountRecordEntity recordEntity = accountRecordDao.findByBusAndOrderNo(AccountRecordBusEnum.CHARGE.getIndex(), orderNo);
        if (recordEntity.getStatus().equals(AccountRecordStatusEnum.DONE.getIndex())) {
            return;
        }
        //金额不正确
        if (recordEntity.getAmount().multiply(new BigDecimal(100)).compareTo(totalPay) != 0) {
            return;
        }
        Long userId = recordEntity.getToUserId();
        findByUserIdAndType(userId, recordEntity.getType());
        accountDao.increase(userId, recordEntity.getType(), recordEntity.getAmount());
        AccountEntity accountEntity = findByUserIdAndType(userId, recordEntity.getType());
        recordEntity.setStatus(AccountRecordStatusEnum.DONE.getIndex());
        recordEntity.setToNowAmount(accountEntity.getAmount());
        accountRecordDao.update(recordEntity);
        afterRecharge(userId,recordEntity.getAmount());
    }

    //TODO 充值成功以后  1-冲1000送200  2-升级
    void afterRecharge(Long userId, BigDecimal amount) {
        int tem = amount.intValue()%1000*200;
        if(tem>0){
            increase(userId,new BigDecimal(tem),"充值赠送","",AccountTypeEnum.CEC.getIndex(),AccountRecordBusEnum.REWARD.getIndex());
        }
        //TODO 送经验值
    }

    @Autowired
    private WxPayService wxPayService;

    @Override
    public List<AccountEntity> findByUserId(Long userId) {
        return accountDao.findByUserId(userId);
    }

    @Autowired
    private AccountRecordDao accountRecordDao;
}
